//
//  NetClient.m
//  ImGuider
//
//  Created by llt on 2017/4/12.
//  Copyright © 2017年 imguider. All rights reserved.
//

#import "NetClient.h"
#import "FileManager.h"
#import <AFNetworkActivityIndicatorManager.h>

@implementation NetClient

static NetClient *_sharedClient = nil;

#pragma mark -初始化
+ (instancetype)sharedClient {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedClient = [[NetClient alloc] initWithBaseURL:[NSURL URLWithString:[AppManager sharedManager].baseURLStr]];
        [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
    });
    return _sharedClient;
}

+ (instancetype)changeClient {
    _sharedClient = [[NetClient alloc] initWithBaseURL:[NSURL URLWithString:[AppManager sharedManager].baseURLStr]];
    return _sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    }
    
    self.securityPolicy.validatesDomainName = NO;
    self.responseSerializer = [AFJSONResponseSerializer serializer];
    self.requestSerializer = [AFJSONRequestSerializer serializer];
    self.requestSerializer.timeoutInterval = 30;
    self.operationQueue.maxConcurrentOperationCount = 3;
    self.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", @"text/javascript", @"text/json", @"text/html", nil];
    // 所有 NSNull 的值，变成 nil。
    ((AFJSONResponseSerializer*)self.responseSerializer).removesKeysWithNullValues = YES;
    [self.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [self.requestSerializer setValue:url.absoluteString forHTTPHeaderField:@"Referer"];
    if ([UserManager sharedManager].token) {
        [self.requestSerializer setValue:[UserManager sharedManager].token forHTTPHeaderField:@"token"];
    }
    
    [self.requestSerializer setValue:@"ios" forHTTPHeaderField:@"platform"];
    
    self.securityPolicy.allowInvalidCertificates = YES;
    
    return self;
}

#pragma mark -请求

- (void)requestJsonDataWithPath:(NSString *)aPath
                     withParams:(NSDictionary*)params
                      needCache:(BOOL)needCache
                 withMethodType:(RequestMethod)method
                  autoShowError:(BOOL)autoShowError
                       andBlock:(void (^)(id data, NSError *error))block {
    [self requestJsonDataWithPath:aPath withParams:params needCache:needCache withMethodType:method autoShowError:autoShowError retryingNumberOfTimes:nil error:nil progress:nil andBlock:block];
}

- (void)requestJsonDataWithPath:(NSString *)aPath
                     withParams:(NSDictionary*)params
                      needCache:(BOOL)needCache
                 withMethodType:(RequestMethod)method
                  autoShowError:(BOOL)autoShowError
                       progress:(void (^)(NSProgress *error))progress
                       andBlock:(void (^)(id data, NSError *error))block {
    
    [self requestJsonDataWithPath:aPath withParams:params needCache:needCache withMethodType:method autoShowError:autoShowError retryingNumberOfTimes:nil error:nil progress:progress andBlock:block];
}

- (void)requestJsonDataWithPath:(NSString *)aPath
                     withParams:(NSDictionary*)params
                      needCache:(BOOL)needCache
                 withMethodType:(RequestMethod)method
                  autoShowError:(BOOL)autoShowError
          retryingNumberOfTimes:(NSNumber *)ntimes
                       andBlock:(void (^)(id data, NSError *error))block {
    
    [self requestJsonDataWithPath:aPath withParams:params needCache:needCache withMethodType:method autoShowError:autoShowError retryingNumberOfTimes:ntimes error:nil progress:nil andBlock:block];
}

- (void)requestJsonDataWithPath:(NSString *)aPath
                     withParams:(NSDictionary*)params
                      needCache:(BOOL)needCache
                 withMethodType:(RequestMethod)method
                  autoShowError:(BOOL)autoShowError
          retryingNumberOfTimes:(NSNumber *)ntimes
                          error:(NSError *)error
                       progress:(void (^)(NSProgress *error))progress
                       andBlock:(void (^)(id data, NSError *error))block {
    
    
	CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
    
    if (!aPath || aPath.length <= 0) {
        if (block) {
            NSError *error = [NSError errorWithDomain:[AppManager sharedManager].baseURLStr code:-1 userInfo:@{@"msg":MYLocalizedString(@"PUBLIC_SYSTEM_ERROR", nil)}];
            
            block(nil,error);
        }
        
        return;
    }
    
    //log请求数据
    aPath = [aPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    NSMutableString *localPath = [aPath mutableCopy];
    
    if (params) {
        [localPath appendString:params.description];
    }
    
    if (ntimes && ntimes.integerValue <= 0) {
        
        IGLog(@"\n===========response===========\n%@:\n%@", aPath, error);
        
        if (autoShowError) [IGUtils showToast:[IGUtils tipFromError:error]];
        
        id responseObject = nil;
        
        if (needCache) {
            responseObject = [FileManager loadResponseWithPath:localPath];
            if (![responseObject isKindOfClass:[NSDictionary class]]) {
                responseObject = nil;
            }
        }
        
        if (block) {
            block(responseObject[@"result"], error);
        }
    
        return;
    }
    
    NSString *chid = [UserManager sharedManager].chid;
    
    if (chid) {
        
        [self.requestSerializer setValue:chid forHTTPHeaderField:@"chid"];
    }
    
    [self.requestSerializer setValue:[AppManager sharedManager].language forHTTPHeaderField:@"lang"];
    
    [self.requestSerializer setValue:[AppManager sharedManager].currentCountryCode forHTTPHeaderField:@"country"];
    //    发起请求
    switch (method) {
        case Get:{
            
            @weakify(self);
            [self GET:aPath parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
                if (progress) {
                    progress(downloadProgress);
                }
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                @strongify(self);
                
                [self successWithResponse:responseObject aPath:aPath localPath:localPath needCache:needCache autoShowError:autoShowError block:block];
                
                CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
                
                IGLog(@"--成功---%@-----的耗时 %f",aPath, (startTime - endTime));
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                @strongify(self);
                [self requestJsonDataWithPath:aPath withParams:params needCache:needCache withMethodType:method autoShowError:autoShowError retryingNumberOfTimes:@(ntimes.integerValue - 1) error:error progress:progress andBlock:block];
                
                CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
                
                IGLog(@"--失败---%@-----的耗时 %f",aPath, (startTime - endTime));
            }];
            
            break;
        }
        case Post:{
            @weakify(self);
            [self POST:aPath parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
                if (progress) {
                    progress(downloadProgress);
                }
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                @strongify(self);
                
                [self successWithResponse:responseObject aPath:aPath localPath:localPath needCache:needCache autoShowError:autoShowError block:block];
                CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
                
                IGLog(@"--成功---%@-----的耗时 %f",aPath, (startTime - endTime));
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                @strongify(self);
                [self requestJsonDataWithPath:aPath withParams:params needCache:needCache withMethodType:method autoShowError:autoShowError retryingNumberOfTimes:@(ntimes.integerValue - 1) error:error progress:progress andBlock:block];
                
                CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
                
                IGLog(@"--失败---%@-----的耗时 %f",aPath, (startTime - endTime));
                
            }];
            break;
        }
        default:
            break;
    }
}


- (void)uploadImageWithImage:(UIImage *)image path:(NSString *)path name:(NSString *)name progress:(void (^)(NSProgress *error))progress andBlock:(void (^)(id data, NSError *error))block {
    
    NSData *data = UIImageJPEGRepresentation(image, 0.5);
    NSString *fileName = [NSString stringWithFormat:@"%@.jpg", [[NSDate date] stringWithFormat: @"yyyyMMddHHmmss"]];
    @weakify(self);
    [self POST:path parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        [formData appendPartWithFileData:data name:name fileName:fileName mimeType:@"image/jpeg"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        if (progress) {
            progress(uploadProgress);
        }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        @strongify(self);
        id error = [self handleResponse:responseObject autoShowError:NO];
        
        if (block) {
            if (error) {
                
                block(nil, error);
            }else{
                
                block(responseObject[@"result"], error);
            }
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (block) {
            block(nil, error);
        }
    }];
}

//- (NSURLSessionDownloadTask *)downLoadFileWithUrlString:(NSString *)urlString progress:(void (^)(NSProgress *progress))progress andBlock:(void (^)(id data, NSError *error))block {
//
//    // 2. 创建下载路径和请求对象
//    NSURL *URL = [NSURL URLWithString:urlString];
//    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
//
//    NSURLSessionDownloadTask *downloadTask = [self downloadTaskWithRequest:request progress:^(NSProgress *downloadProgress) {
//
//        if (progress) {
//            progress(downloadProgress);
//        }
//
//    } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
//        NSString *pathStr = [FileManager pathInDownloadDirectory:urlString];
//        return [NSURL URLWithString:pathStr];
//
//    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
//
//        if (block) {
//            block(response,error);
//        }
//    }];
//    // 4. 开启下载任务
//    [downloadTask resume];
//    return downloadTask;
//}

#pragma mark -成功处理

- (void)successWithResponse:(id)responseObject aPath:(NSString *)aPath localPath:(NSString *)localPath needCache:(BOOL)needCache autoShowError:(BOOL)autoShowError block:(void (^)(id data, NSError *error))block {
    
    IGLog(@"\n===========response===========\n%@:\n%@", aPath, responseObject);
    id error = [self handleResponse:responseObject autoShowError:autoShowError];
    
    if (error) {
        
        if (needCache) {
            responseObject = [FileManager loadResponseWithPath:localPath];
            
            if (![responseObject isKindOfClass:[NSDictionary class]]) {
                responseObject = nil;
            }
        }
    } else {
        
        if (needCache && [responseObject isKindOfClass:[NSDictionary class]]) {
            
            [FileManager saveResponseData:responseObject toPath:localPath];
        }
    }
    if (block) {
        block(responseObject[@"result"], error);
    }
}

#pragma mark -错误处理
// 网络请求成功 中的失败处理
- (id)handleResponse:(id)responseJSON autoShowError:(BOOL)autoShowError{
    NSError *error = nil;
    //code为非0值时，表示有错
    
    NSInteger status = [[responseJSON objectForKey:@"status"] integerValue];
    
    if (status != 0) {
        
        NSInteger errcode = [[responseJSON objectForKey:@"errcode"] integerValue];
        error = [NSError errorWithDomain:[AppManager sharedManager].baseURLStr code:errcode userInfo:responseJSON];
        if (errcode == 500) {//用户未登录
            //已登录的状态要抹掉
            
            //更新 UI 要延迟 >1.0 秒，否则屏幕可能会不响应触摸事件。。暂不知为何
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                //                [((AppDelegate *)[UIApplication sharedApplication].delegate) setupLoginViewController];
                
                [IGUtils showToast:MYLocalizedString(@"PUBLIC_LOGIN_TIMEOUT", nil)];
                [UserManager sharedManager].user = nil;
                [UserManager sharedManager].token = nil;
                
                [NetClient changeClient];
                [[NSNotificationCenter defaultCenter] postNotificationName:kRefreshUserNotif object:nil];
            });
            
        }else{
            
            //错误提示
            if (autoShowError) {
                [IGUtils showToast:[IGUtils tipFromError:error]];
            }
        }
    }
    return error;
}

@end

